package pers.twf.twfRpc.server;

import io.vertx.core.Handler;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpServerResponse;
import pers.twf.twfRpc.RpcApplication;
import pers.twf.twfRpc.model.RpcRequest;
import pers.twf.twfRpc.model.RpcResponse;
import pers.twf.twfRpc.registry.LocalRegistry;
import pers.twf.twfRpc.serializer.Serializer;
import pers.twf.twfRpc.serializer.SerializerFactory;

import java.io.IOException;
import java.lang.reflect.Method;


/**
 * 请求处理器
 * 反序列化请求为对象，获取参数
 * 通过服务名称从本地注册器获取服务实现，
 * 反射调用方法
 * 序列化返回结果，写入响应
 */

//注意，不同web服务器的处理器实现不同，此处为vertx通过实现Handler接口处理
public class HttpServerHander implements Handler<HttpServerRequest> {

    @Override
    public void handle(HttpServerRequest httpServerRequest) {
// 指定序列化器
        final Serializer serializer = SerializerFactory.getInstance(RpcApplication.getRpcConfig().getSerializer());

//        日志
        System.out.println("Received request:"+httpServerRequest.method()+" "+httpServerRequest.uri());
//        异步处理请求
        httpServerRequest.bodyHandler(body -> {
            byte[] bytes = body.getBytes();
            RpcRequest rpcRequest = null;
            try {
                rpcRequest = serializer.deserialize(bytes, RpcRequest.class);
            } catch (IOException e) {
                e.printStackTrace();
            }
//            构造返回对象
            RpcResponse rpcResponse = new RpcResponse();

            if (rpcRequest==null){
                rpcResponse.setMessage("request is null");
                doResponse(httpServerRequest,rpcResponse,serializer);
               return;
            }

            try {
//                反射调用
                Class<?> aClass = LocalRegistry.get(rpcRequest.getServiceName());
                Method method = aClass.getMethod(rpcRequest.getMethodName(), rpcRequest.getParameterTypes());
                Object result = method.invoke(aClass.newInstance(), rpcRequest.getParameters());
//                封装结果
                rpcResponse.setData(result);
                rpcResponse.setDataType(method.getReturnType());
                rpcResponse.setMessage("ok");
            } catch (Exception e) {
                e.printStackTrace();
                rpcResponse.setException(e);
                rpcResponse.setMessage(e.getMessage());
            }
            doResponse(httpServerRequest,rpcResponse,serializer);
        });
    }

    private void doResponse(HttpServerRequest httpServerRequest, RpcResponse rpcResponse, Serializer serializer) {
        HttpServerResponse httpServerResponse = httpServerRequest.response().putHeader("contnet-type", "application/json");
        try {
            byte[] serialize = serializer.serialize(rpcResponse);
            httpServerResponse.end(Buffer.buffer(serialize));
        } catch (IOException e) {
            e.printStackTrace();
            httpServerResponse.end(Buffer.buffer());
        }
    }
}
